home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_354 / keymacro / keymacro-handler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  16KB  |  844 lines

  1. /****************************************************************************
  2. *
  3. *    KeyMacro.Handler.c ----    KeyMacro handler.
  4. *
  5. *    Author ----------------    Olaf Barthel, MXM
  6. *                Brabeckstrasse 35
  7. *                D-3000 Hannover 71
  8. *
  9. *    KeyMacro  ©  Copyright  1990  by  MXM;  Executable  program,
  10. *    documentation  and  source  code are shareware.  If you like
  11. *    this  program  a  small donation will entitle you to receive
  12. *    updates and new programs from MXM.
  13. *
  14. ****************************************************************************/
  15.  
  16.     /* Function prototypes. */
  17.  
  18. VOID            FreeString(BPTR);
  19. BPTR            CreateBSTR(char *);
  20. BPTR            CopyPath(VOID);
  21. VOID            FakeCLI(VOID);
  22. VOID            ClearPath(BPTR);
  23. VOID            StopFakery(VOID);
  24. VOID *            DeleteMacroMsg(struct MacroMessage *);
  25. VOID *            SendMacroMsg(struct MacroMessage *,struct MsgPort *);
  26. VOID            Executor(VOID);
  27. struct InputEvent *    EventHandler(struct InputEvent *);
  28. struct MacroKey *    FindMacroKey(LONG,LONG);
  29. LONG            CreateHandler(VOID);
  30. VOID            DeleteHandler(VOID);
  31.  
  32. LONG            _main(VOID);
  33.  
  34.     /* The magic stuff. */
  35.  
  36. #pragma regcall(EventHandler(a0))
  37.  
  38.     /* Shared library identifiers. */
  39.  
  40. struct MXMBase        *MXMBase;
  41. struct IntuitionBase    *IntuitionBase;
  42. struct Library        *ConsoleDevice;
  43. extern struct ExecBase    *SysBase;
  44.  
  45.     /* Global handshake data. */
  46.  
  47. struct MSeg        *MSeg;
  48. struct KeyEquivalent    *EquList;
  49.  
  50.     /* Process<->Process communication data. */
  51.  
  52. struct Process        *ExecuteProc;
  53. struct MsgPort        *ExecutePort;
  54.  
  55.     /* Input device data. */
  56.  
  57. struct MsgPort        *InputDevPort;
  58. struct IOStdReq        *InputRequestBlock;
  59. struct Interrupt    *InputHandler;
  60. struct InputEvent    *FakeInputEvent;
  61.  
  62.     /* _main():
  63.      *
  64.      *    This is the entry point to the handler process.
  65.      */
  66.  
  67. LONG
  68. _main()
  69. {
  70.     struct Process        *ThatsMe;
  71.     ULONG             SignalSet;
  72.     struct MacroMessage    *MacroMsg;
  73.     LONG             SigBit;
  74.     LONG             i;
  75.  
  76.         /* Do I know myself? */
  77.  
  78.     ThatsMe = (struct Process *)SysBase -> ThisTask;
  79.  
  80.         /* Don't let anybody call us from CLI. */
  81.  
  82.     if(ThatsMe -> pr_CLI)
  83.         goto Quit;
  84.  
  85.         /* Can we find the global MsgPort? */
  86.  
  87.     if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
  88.     {
  89.         Forbid();
  90.  
  91.         Signal(MSeg -> Father,MSeg -> RingBack);
  92.  
  93.         goto Quit;
  94.     }
  95.  
  96.         /* This older revision probably doesn't support
  97.          * some newer structure tags -> exit.
  98.          */
  99.  
  100.     if(MSeg -> Revision < REVISION)
  101.     {
  102.         Forbid();
  103.  
  104.         Signal(MSeg -> Father,MSeg -> RingBack);
  105.  
  106.         goto Quit;
  107.     }
  108.  
  109.         /* The MsgPort is already owned by someone
  110.          * else.
  111.          */
  112.  
  113.     if(MSeg -> Port . mp_Flags & PA_SIGNAL)
  114.     {
  115.         Forbid();
  116.  
  117.         Signal(MSeg -> Father,MSeg -> RingBack);
  118.  
  119.         goto Quit;
  120.     }
  121.  
  122.         /* Open mxm.library. */
  123.  
  124.     if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",34)))
  125.     {
  126.         Forbid();
  127.  
  128.         Signal(MSeg -> Father,MSeg -> RingBack);
  129.  
  130.         goto Quit;
  131.     }
  132.  
  133.         /* Initialize the input.device handler. */
  134.  
  135.     if(!CreateHandler())
  136.     {
  137.         DeleteHandler();
  138.  
  139.         CloseLibrary((struct Library *)MXMBase);
  140.  
  141.         Forbid();
  142.  
  143.         Signal(MSeg -> Father,MSeg -> RingBack);
  144.  
  145.         goto Quit;
  146.     }
  147.  
  148.         /* Extract shared library identifiers. */
  149.  
  150.     IntuitionBase = (struct IntuitionBase *)MXMBase -> IntuitionBase;
  151.     ConsoleDevice = (struct Library *)MXMBase -> ConsoleDevice;
  152.  
  153.         /* Allocate a fake InputEvent structure. */
  154.  
  155.     if(!(FakeInputEvent = (struct InputEvent *)AllocRem(sizeof(struct InputEvent),MEMF_PUBLIC)))
  156.     {
  157.         DeleteHandler();
  158.         CloseLibrary((struct Library *)MXMBase);
  159.  
  160.         Forbid();
  161.  
  162.         Signal(MSeg -> Father,MSeg -> RingBack);
  163.  
  164.         goto Quit;
  165.     }
  166.  
  167.         /* Allocate a signal bit. */
  168.  
  169.     if((SigBit = AllocSignal(-1)) == -1)
  170.     {
  171.         FreeRem(FakeInputEvent);
  172.  
  173.         DeleteHandler();
  174.  
  175.         CloseLibrary((struct Library *)MXMBase);
  176.  
  177.         Forbid();
  178.  
  179.         MSeg -> Child = NULL;
  180.         Signal(MSeg -> Father,MSeg -> RingBack);
  181.  
  182.         goto Quit;
  183.     }
  184.  
  185.         /* Start the executing process. */
  186.  
  187.     MSeg -> Child = (struct Task *)ThatsMe;
  188.  
  189.     if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro.exec",10,Executor,4000)))
  190.     {
  191.         FreeSignal(SigBit);
  192.  
  193.         FreeRem(FakeInputEvent);
  194.  
  195.         DeleteHandler();
  196.  
  197.         CloseLibrary((struct Library *)MXMBase);
  198.  
  199.         Forbid();
  200.  
  201.         MSeg -> Child = NULL;
  202.         Signal(MSeg -> Father,MSeg -> RingBack);
  203.  
  204.         goto Quit;
  205.     }
  206.  
  207.         /* Wait for handshake signal. */
  208.  
  209.     Wait(SIG_SHAKE);
  210.  
  211.         /* Process creation failed. */
  212.  
  213.     if(!ExecuteProc)
  214.     {
  215.         FreeSignal(SigBit);
  216.  
  217.         FreeRem(FakeInputEvent);
  218.  
  219.         DeleteHandler();
  220.         CloseLibrary((struct Library *)MXMBase);
  221.  
  222.         Forbid();
  223.  
  224.         MSeg -> Child = NULL;
  225.         Signal(MSeg -> Father,MSeg -> RingBack);
  226.  
  227.         goto Quit;
  228.     }
  229.  
  230.         /* Now we are truly running. */
  231.  
  232.     Signal(MSeg -> Father,MSeg -> RingBack);
  233.  
  234.     MSeg -> Father = NULL;
  235.  
  236.         /* Re-init the MsgPort flags. */
  237.  
  238.     MSeg -> Port . mp_Flags        = PA_SIGNAL;
  239.     MSeg -> Port . mp_SigBit    = SigBit;
  240.     MSeg -> Port . mp_SigTask    = MSeg -> Child;
  241.  
  242.         /* Wait until somebody kicks us out. */
  243.  
  244.     FOREVER
  245.     {
  246.         SignalSet = Wait(SIG_CLOSE | SIG_PORT);
  247.  
  248.             /* We are to shut down. */
  249.  
  250.         if(SignalSet & SIG_CLOSE)
  251.         {
  252.             FreeSignal(SigBit);
  253.  
  254.             FreeRem(FakeInputEvent);
  255.  
  256.             DeleteHandler();
  257.  
  258.             if(ExecuteProc)
  259.             {
  260.                 Signal((struct Task *)ExecuteProc,SIG_CLOSE);
  261.  
  262.                 Wait(SIG_SHAKE);
  263.             }
  264.  
  265.             CloseLibrary((struct Library *)MXMBase);
  266.  
  267.             Forbid();
  268.  
  269.             Signal(MSeg -> Father,SIG_CLOSE);
  270.  
  271.             goto Quit;
  272.         }
  273.  
  274.             /* A message arrived at our home port. */
  275.  
  276.         if(SignalSet & SIG_PORT)
  277.         {
  278.                 /* Walk through the list of messages. */
  279.  
  280.             while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
  281.             {
  282.                     /* Execute a keyboard macro. */
  283.  
  284.                 if(MacroMsg -> mm_Type == MM_INPUT)
  285.                 {
  286.                     struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
  287.  
  288.                     if(TempMacroKey)
  289.                     {
  290.                             /* Let the execute process run the command. */
  291.  
  292.                         if(TempMacroKey -> mk_Type == MK_COMMAND)
  293.                         {
  294.                             struct MacroMessage CommandMsg;
  295.  
  296.                             CommandMsg . mm_Type        = MM_EXECUTE;
  297.                             CommandMsg . mm_FileName    = TempMacroKey -> mk_String;
  298.                             CommandMsg . mm_WindowName    = TempMacroKey -> mk_Window;
  299.  
  300.                             SendMacroMsg(&CommandMsg,ExecutePort);
  301.                         }
  302.  
  303.                             /* Build a keyboard macro. */
  304.  
  305.                         if(TempMacroKey -> mk_Type == MK_WORD)
  306.                         {
  307.                             InputRequestBlock -> io_Command    = IND_WRITEEVENT;
  308.                             InputRequestBlock -> io_Data    = (APTR)FakeInputEvent;
  309.  
  310.                             memset(FakeInputEvent,0,sizeof(struct InputEvent));
  311.  
  312.                             FakeInputEvent -> ie_Class = IECLASS_RAWKEY;
  313.  
  314.                             for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
  315.                                 if(InvertKey(TempMacroKey -> mk_String[i],FakeInputEvent,IK_USEIKM,NULL))
  316.                                     DoIO(InputRequestBlock);
  317.                         }
  318.                     }
  319.                 }
  320.  
  321.                     /* This is a request to update the
  322.                      * macro keys.
  323.                      */
  324.  
  325.                 if(MacroMsg -> mm_Type == MM_UPDATE)
  326.                 {
  327.                     if(MSeg -> MacroList)
  328.                     {
  329.                         for(i = 0 ; i < MSeg -> NumMacros ; i++)
  330.                         {
  331.                             if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  332.                                 continue;
  333.  
  334.                             if(MSeg -> MacroList[i] . mk_String)
  335.                                 FreeRem(MSeg -> MacroList[i] . mk_String);
  336.  
  337.                             if(MSeg -> MacroList[i] . mk_Window)
  338.                                 FreeRem(MSeg -> MacroList[i] . mk_Window);
  339.                         }
  340.  
  341.                         FreeRem(MSeg -> MacroList);
  342.                     }
  343.  
  344.                     MSeg -> NumMacros = MacroMsg -> mm_NumMacros;
  345.                     MSeg -> MacroList = MacroMsg -> mm_MacroList;
  346.                 }
  347.  
  348.                     /* Remove the message. */
  349.  
  350.                 DeleteMacroMsg(MacroMsg);
  351.             }
  352.         }
  353.     }
  354.  
  355. Quit:    ;
  356. }
  357.  
  358.     /* FreeString(Byte):
  359.      *
  360.      *    Frees the memory occupied by the contents of a BSTR.
  361.      */
  362.  
  363. VOID
  364. FreeString(BPTR Byte)
  365. {
  366.     LONG *Ptr = (LONG *)BADDR(Byte);
  367.  
  368.     FreeMem(Ptr - 1,Ptr[-1]);
  369. }
  370.  
  371.     /* CreateBSTR(s):
  372.      *
  373.      *    Allocates enough memory to hold the contents of
  374.      *    a given string and makes it a BSTR.
  375.      */
  376.  
  377. BPTR
  378. CreateBSTR(char *s)
  379. {
  380.     LONG  Length = strlen(s);
  381.     LONG  BlockLength = (Length + 8) & ~3;
  382.     char *Byte;
  383.  
  384.     if(!(Byte = (char *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
  385.         return(NULL);
  386.  
  387.     *(LONG *)Byte = BlockLength;
  388.  
  389.     Byte[4] = Length;
  390.     strncpy(Byte + 5,s,Length);
  391.  
  392.     return((LONG)(Byte + 4) >> 2);
  393. }
  394.  
  395.     /* CopyPath():
  396.      *
  397.      *    Builds a fake pathlist inherited from any valid
  398.      *    CLI process or Workbench.
  399.      */
  400.  
  401. BPTR
  402. CopyPath()
  403. {
  404.     struct Process            *Father;
  405.     struct CommandLineInterface    *CLI;
  406.     BPTR                *Next1,*Next2,*Last,NewPath = NULL;
  407.  
  408.     Last = &NewPath;
  409.  
  410.         /* If using ARP this will also give us a valid
  411.          * pathlist.
  412.          */
  413.  
  414.     if(!(Father = (struct Process *)FindTask("Workbench")))
  415.         if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
  416.             if(!(Father = (struct Process *)FindTask("New CLI")))
  417.                 if(!(Father = (struct Process *)FindTask("Initial CLI")))
  418.                     return(NULL);
  419.  
  420.     if(!(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI)))
  421.         return(NULL);
  422.  
  423.     for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
  424.     {
  425.         if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
  426.             break;
  427.  
  428.         *Last = (LONG)Next2 >> 2;
  429.         Last = Next2;
  430.  
  431.         Next2[1] = (BPTR)DupLock(Next1[1]);
  432.         Next2[0] = NULL;
  433.     }
  434.  
  435.     return(NewPath);
  436. }
  437.  
  438.     /* FakeCLI():
  439.      *
  440.      *    Creates a fake CLI structure for our process. This
  441.      *    includes pathlist, currentdir, prompt and stack.
  442.      */
  443.  
  444. VOID
  445. FakeCLI()
  446. {
  447.     struct CommandLineInterface    *CLI;
  448.     struct Process            *MyProcess = (struct Process *)SysBase -> ThisTask;
  449.  
  450.     if(!(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR)))
  451.         return;
  452.  
  453.     MyProcess -> pr_CLI = (LONG)CLI >> 2;
  454.  
  455.     CLI -> cli_SetName    = CreateBSTR("SYS:");
  456.     CLI -> cli_Prompt    = CreateBSTR("%N> ");
  457.     CLI -> cli_DefaultStack    = 4000;
  458.  
  459.     CurrentDir(Lock("SYS:",ACCESS_READ));
  460.  
  461.     CLI -> cli_CommandDir    = CopyPath();
  462. }
  463.  
  464.     /* ClearPath(InitPath):
  465.      *
  466.      *    Frees the contents of our fake pathlist.
  467.      */
  468.  
  469. VOID
  470. ClearPath(BPTR InitPath)
  471. {
  472.     BPTR *Next,*Path;
  473.  
  474.     for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
  475.     {
  476.         Next = (BPTR *)BADDR(Path[0]);
  477.  
  478.         if(Path[1])
  479.             UnLock(Path[1]);
  480.  
  481.         FreeMem(Path,2 * sizeof(BPTR));
  482.     }
  483. }
  484.  
  485.     /* StopFakery():
  486.      *
  487.      *    Removes the contents of our fake CLI structure.
  488.      */
  489.  
  490. VOID
  491. StopFakery()
  492. {
  493.     BPTR                 MyCD = (BPTR)CurrentDir(NULL);
  494.     struct Process            *MyProcess = (struct Process *)SysBase -> ThisTask;
  495.     struct CommandLineInterface    *CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI);
  496.  
  497.     if(!CLI)
  498.         return;
  499.  
  500.     if(MyCD)
  501.         UnLock(MyCD);
  502.  
  503.     FreeString(CLI -> cli_SetName);
  504.     FreeString(CLI -> cli_Prompt);
  505.  
  506.     ClearPath(CLI -> cli_CommandDir);
  507.  
  508.     MyProcess -> pr_CLI = NULL;
  509.  
  510.     FreeMem(CLI,sizeof(struct CommandLineInterface));
  511. }
  512.  
  513.     /* DeleteMacroMsg(scm_Msg):
  514.      *
  515.      *    Remove a message from memory.
  516.      */
  517.  
  518. VOID *
  519. DeleteMacroMsg(struct MacroMessage *scm_Msg)
  520. {
  521.     if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == (char *)scm_Msg)
  522.         FreeRem(scm_Msg);
  523.  
  524.     return(NULL);
  525. }
  526.  
  527.     /* SendMacroMsg(scm_Msg,scm_Port):
  528.      *
  529.      *    Post a cloned macro message to a MsgPort.
  530.      */
  531.  
  532. VOID *
  533. SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port)
  534. {
  535.     struct MacroMessage *scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR);
  536.  
  537.     if(scm_TempMsg)
  538.     {
  539.         CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
  540.  
  541.         scm_TempMsg -> mm_Message . mn_Node . ln_Name    = (char *)scm_TempMsg;
  542.         scm_TempMsg -> mm_Message . mn_ReplyPort    = NULL;
  543.         scm_TempMsg -> mm_Message . mn_Length        = sizeof(struct MacroMessage);
  544.  
  545.         PutMsg(scm_Port,(struct Message *)scm_TempMsg);
  546.     }
  547.  
  548.     return((VOID *)scm_TempMsg);
  549. }
  550.  
  551.     /* Executor():
  552.      *
  553.      *    This is the dummy process to execute programs.
  554.      */
  555.  
  556. VOID
  557. Executor()
  558. {
  559.     ULONG             SignalSet;
  560.     BPTR             NIL;
  561.     struct MacroMessage    *ExecuteMsg;
  562.     struct Window        *TheWindow;
  563.     char             TempLine[300];
  564.  
  565.     geta4();
  566.  
  567.         /* Try to allocate a port (we can't use our builtin
  568.          * DOS port since we are actually calling DOS
  569.          * routines which may mix up the messages coming
  570.          * in).
  571.          */
  572.  
  573.     if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
  574.     {
  575.         Forbid();
  576.  
  577.         ExecuteProc = NULL;
  578.  
  579.         Signal(MSeg -> Child,SIG_SHAKE);
  580.  
  581.         goto Quit;
  582.     }
  583.  
  584.         /* Open the NULL-Handler. */
  585.  
  586.     if(!(NIL = Open("NULL:",MODE_NEWFILE)))
  587.     {
  588.         Forbid();
  589.  
  590.         ExecuteProc = NULL;
  591.  
  592.         Signal(MSeg -> Child,SIG_SHAKE);
  593.         DeletePort(ExecutePort);
  594.  
  595.         goto Quit;
  596.     }
  597.  
  598.         /* Pretend to be a CLI. */
  599.  
  600.     FakeCLI();
  601.     {
  602.         struct Process *ThatsMe = (struct Process *)SysBase -> ThisTask;
  603.  
  604.             /* These are inherited from the father process,
  605.              * we had better cleared them out.
  606.              */
  607.  
  608.         ThatsMe -> pr_ConsoleTask    = (APTR)DeviceProc("NULL:");
  609.         ThatsMe -> pr_WindowPtr        = (APTR)-1;
  610.  
  611.             /* This path leads nowhere. */
  612.  
  613.         ThatsMe -> pr_CIS        = NIL;
  614.         ThatsMe -> pr_COS        = NIL;
  615.     }
  616.  
  617.         /* We're on the scene now. */
  618.  
  619.     Signal(MSeg -> Child,SIG_SHAKE);
  620.  
  621.     FOREVER
  622.     {
  623.         SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
  624.  
  625.             /* Shut down? */
  626.  
  627.         if(SignalSet & SIG_CLOSE)
  628.         {
  629.             StopFakery();
  630.             Close(NIL);
  631.             DeletePort(ExecutePort);
  632.  
  633.             ExecuteProc = NULL;
  634.  
  635.             Forbid();
  636.  
  637.             Signal(MSeg -> Child,SIG_SHAKE);
  638.  
  639.             goto Quit;
  640.         }
  641.  
  642.             /* Execute a command? */
  643.  
  644.         while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
  645.         {
  646.             TheWindow = NULL;
  647.  
  648.                 /* Try to find a matching window title. */
  649.  
  650.             if(ExecuteMsg -> mm_WindowName)
  651.             {
  652.                 ULONG IntuiLock;
  653.  
  654.                 struct Screen *ExScreen;
  655.                 struct Window *ExWindow;
  656.  
  657.                 IntuiLock = LockIBase(NULL);
  658.  
  659.                 ExScreen = IntuitionBase -> FirstScreen;
  660.  
  661.                 do
  662.                 {
  663.                     ExWindow = ExScreen -> FirstWindow;
  664.  
  665.                     do
  666.                     {
  667.                         if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
  668.                         {
  669.                             UnlockIBase(IntuiLock);
  670.  
  671.                             TheWindow = ExWindow;
  672.  
  673.                             goto SkipLoop;
  674.                         }
  675.                     }
  676.                     while(ExWindow = ExWindow -> NextWindow);
  677.                 }
  678.                 while(ExScreen = ExScreen -> NextScreen);
  679.  
  680.                 UnlockIBase(IntuiLock);
  681.             }
  682.  
  683.                 /* No chance, execute the command. */
  684.  
  685.             strcpy(TempLine,"C:Run <NULL: >NULL: ");
  686.             strcat(TempLine,ExecuteMsg -> mm_FileName);
  687.  
  688.             Execute(TempLine,NULL,NIL);
  689.  
  690. SkipLoop:        DeleteMacroMsg(ExecuteMsg);
  691.  
  692.                 /* Found a window? Bring it to the front. */
  693.  
  694.             if(TheWindow)
  695.             {
  696.                 WindowToFront(TheWindow);
  697.                 ScreenToFront(TheWindow -> WScreen);
  698.                 ActivateWindow(TheWindow);
  699.             }
  700.         }
  701.     }
  702.  
  703.         /* Finished, fall through. */
  704.  
  705. Quit:    ;
  706. }
  707.  
  708.     /* FindMacroKey(Code,Qualifier):
  709.      *
  710.      *    Find a macro key entry in the linked list of
  711.      *    macro key structures.
  712.      */
  713.  
  714. struct MacroKey *
  715. FindMacroKey(LONG Code,LONG Qualifier)
  716. {
  717.     LONG i;
  718.  
  719.     if(!MSeg -> MacroList)
  720.         return(NULL);
  721.  
  722.     for(i = 0 ; i < MSeg -> NumMacros ; i++)
  723.     {
  724.         if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  725.             continue;
  726.  
  727.         if(MSeg -> MacroList[i] . mk_CommandKey == Code && (Qualifier & MSeg -> MacroList[i] . mk_CommandQualifier) == MSeg -> MacroList[i] . mk_CommandQualifier)
  728.             return(&MSeg -> MacroList[i]);
  729.     }
  730.  
  731.     return(NULL);
  732. }
  733.  
  734.     /* EventHandler(Event):
  735.      *
  736.      *    The input event handler.
  737.      */
  738.  
  739. struct InputEvent *
  740. EventHandler(struct InputEvent *Event)
  741. {
  742.     struct MacroKey *HandlerKey;
  743.  
  744.         /* This is an interrupt, let's start with the register
  745.          * saving.
  746.          */
  747.  
  748.     int_start();
  749.  
  750.     if(Event -> ie_Class == IECLASS_RAWKEY && !(Event -> ie_Code & IECODE_UP_PREFIX))
  751.     {
  752.         if(HandlerKey = (struct MacroKey *)FindMacroKey(Event -> ie_Code,Event -> ie_Qualifier))
  753.         {
  754.             struct MacroMessage HandlerMsg;
  755.  
  756.             HandlerMsg . mm_Type    = MM_INPUT;
  757.             HandlerMsg . mm_MacroKey= HandlerKey;
  758.  
  759.             SendMacroMsg(&HandlerMsg,&MSeg -> Port);
  760.  
  761.             Event -> ie_Class = IECLASS_NULL;
  762.         }
  763.     }
  764.  
  765.         /* Restore the registers. */
  766.  
  767.     int_end();
  768.  
  769.     return(Event);
  770. }
  771.  
  772.     /* CreateHandler():
  773.      *
  774.      *    Initialize the input event handler.
  775.      */
  776.  
  777. LONG
  778. CreateHandler()
  779. {
  780.         /* The basic initialization. */
  781.  
  782.     if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
  783.         return(FALSE);
  784.  
  785.     if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
  786.         return(FALSE);
  787.  
  788.     if(OpenDevice("input.device",0,(struct IORequest *)InputRequestBlock,0))
  789.         return(FALSE);
  790.  
  791.     if(!(InputHandler = (struct Interrupt *)AllocRem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
  792.         return(FALSE);
  793.  
  794.         /* Build the input handler. */
  795.  
  796.     InputHandler -> is_Code            = (VOID *)EventHandler;
  797.     InputHandler -> is_Node . ln_Pri    = 51;
  798.     InputHandler -> is_Node . ln_Name    = "KeyMacro-Handler";
  799.  
  800.         /* Add the handler. */
  801.  
  802.     InputRequestBlock -> io_Command        = IND_ADDHANDLER;
  803.     InputRequestBlock -> io_Data        = (APTR)InputHandler;
  804.  
  805.     if(DoIO((struct IORequest *)InputRequestBlock))
  806.         return(FALSE);
  807.  
  808.     return(TRUE);
  809. }
  810.  
  811.     /* DeleteHandler():
  812.      *
  813.      *    Remove the input event handler.
  814.      */
  815.  
  816. VOID
  817. DeleteHandler()
  818. {
  819.         /* Remove the input handler. */
  820.  
  821.     if(InputRequestBlock)
  822.     {
  823.         if(InputRequestBlock -> io_Device)
  824.         {
  825.             InputRequestBlock -> io_Command    = IND_REMHANDLER;
  826.             InputRequestBlock -> io_Data    = (APTR)InputHandler;
  827.  
  828.             DoIO((struct IORequest *)InputRequestBlock);
  829.  
  830.             CloseDevice((struct IORequest *)InputRequestBlock);
  831.         }
  832.  
  833.         DeleteStdIO(InputRequestBlock);
  834.     }
  835.  
  836.         /* Free the last memory. */
  837.  
  838.     if(InputHandler)
  839.         FreeRem(InputHandler);
  840.  
  841.     if(InputDevPort)
  842.         DeletePort(InputDevPort);
  843. }
  844.